/**
 * js中数据的深浅克隆
 * @Date 2024年3月5日16:00:27
 * @author zhl
 */


// 浅克隆(shallow clone)
// JS中的浅克隆指的是创建一个新对象，该对象与原始对象共享相同属性值。当修改其中任何一个对象时，会影响到两者。即其属性为子项为对象或数组时，指向相同。

// 方式一 Object.assign
// Object.assign() 静态方法将一个或者多个源对象中所有可枚举的自有属性复制到目标对象，并返回修改后的目标对象。
// 语法：`Object.assign(target, ...sources) ` target：需要应用源对象属性的目标对象，修改后将作为返回值。sources：一个或多个包含要应用的属性的源对象。
// 参考：`https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign`
export const shallowCloneByAssign =  function (obj) {
  if (typeof obj !== "object" || obj === null) {
    return obj; // 非对象直接返回
  }
  return Object.assign({}, obj);
}

// 方式二 扩展运算符（...）
export const shallowCloneByOpe = function (obj) {
  if (typeof obj !== "object" || obj === null) {
    return obj; // 非对象直接返回
  }
  return { ...obj };
}

// 深克隆(deep clone)

// 方式一
export const deepClone = function (obj) {
  if (typeof obj !== "object" || obj === null) {
    return obj; // 非对象直接返回
  }
  let copy = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      copy[key] = deepClone(obj[key]);
    }
  }
  return copy;
}

// 方式二 JSON
export const deepCloneByJSON =  function (obj) {
  if (typeof obj !== "object" || obj === null) {
    return obj; // 非对象直接返回
  }
  return JSON.parse(JSON.stringify(obj));
}

/**
 * @description 深度克隆,主要针对多层引用类型的深度克隆:如果该项为null,复制后依旧为null,只是对应的function只是复制的引用地址,所以没有达到复制的效果
 * @param {array||object} o 需要进行深度克隆的引用数据
  * @return {array|| object} newO 复制完成后的数据 
 */
export const deepCloneByMe = function (o){
    if(!typeCheck(o)==="array" || !typeCheck(o)==="object") return o;
    let newO = typeCheck(o) === "array" ? [] : {};
    for(let key in o){
        if(o.hasOwnProperty(key)){
            newO[key] = (o && typeof o[key] === "object") ? (typeCheck(o[key])==="null"?null:deepClone(o[key])):o[key];	
        }
    }
    return newO;
}
